package com.rstar.readerbook;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.util.Vector;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.os.Environment;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;

public class ReaderBook extends Activity implements OnTouchListener{
	private static final String TAG = "ReaderBook"; 
    private static final int MARGINWIDTH = 15; 
    private static final int MARGINHEIGHT = 20;
	
	private int bookmark = 0;
    private File book_file = null;  
    private MappedByteBuffer m_mbBuf = null;  
    private int m_mbBufLen = 0;  
    private int m_mbBufBegin = 0;  
    private int m_mbBufEnd = 0;  
    private String m_strCharsetName = "GBK";  
    private Bitmap m_book_bg = null;  
    private int mWidth;  
    private int mHeight;  
    //private BookTextView bookTextView;
    private Vector<String> m_lines = new Vector<String>();  
  
    private int m_fontSize = 24;  
    private int m_textColor = Color.BLACK;  
    private int m_backColor = 0xffc8c8c8; 
  
    private int mLineCount; 
    private float mVisibleHeight; 
    private float mVisibleWidth; 
    private boolean m_isfirstPage,m_islastPage;  
    private Paint mPaint;  
    private Bitmap mCurPageBitmap, mNextPageBitmap;  
    private Canvas mCurPageCanvas, mNextPageCanvas;  
    private MyApplication application;
    
    //private GestureDetector mGestureDetector;
    private PageWidget mPageWidget;
    private int mSlidingSensitivity;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        init();
        mPageWidget = new PageWidget(this, mWidth, mHeight, mSlidingSensitivity, new PageWidget.OnDragResult() {
			
			public void OnDragResult(boolean isDragOver) {
				if(!isDragOver){
					resetDragOver();
				}
			}
		});
        
        setContentView(mPageWidget);
        
        try {
			openBook(application.getFilePath());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
        mPageWidget.setBitmaps(mCurPageBitmap, mCurPageBitmap);
        mPageWidget.setOnTouchListener(this);
        m_mbBufEnd = m_mbBufBegin = application.getBookMark(application.getFilePath());
        updateContent();
    }

    private void init(){
    	DisplayMetrics metric = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metric);
        int width = metric.widthPixels;     // 屏幕宽度（像素）
        int height = metric.heightPixels;   // 屏幕高度（像素）
        application = (MyApplication)getApplication(); 
        mSlidingSensitivity = application.getSlidingSensitivity();
        m_fontSize = application.getFontSize();
        mWidth = width;  
        mHeight = height;  
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
        mPaint.setTextAlign(Align.LEFT);  
        mPaint.setTextSize(m_fontSize);  
        mPaint.setColor(m_textColor);  
        mVisibleWidth = mWidth - MARGINWIDTH * 2;  
        mVisibleHeight = mHeight - MARGINHEIGHT * 2;  
        mLineCount = (int) (mVisibleHeight / m_fontSize);  
        mCurPageBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); 
        mCurPageCanvas = new Canvas(mCurPageBitmap);
        //bookTextView.setBitmap(mCurPageBitmap);
        mNextPageBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); 
        mNextPageCanvas = new Canvas(mNextPageBitmap);   
        
        if(application.getFilePath() != null && application.getFilePath() != ""){
        	m_strCharsetName = EncodingDetect.getJavaEncode(application.getFilePath()); //获取编码方式
        }
        
/*        mGestureDetector = new GestureSlideExt(this, new GestureSlideExt.OnGestureResult() {
			public void onGestureResult(int direction) {
				 // 涓氬姟閫昏緫澶勭悊
				switch (direction) {
				case GestureSlideExt.GESTURE_UP:
					//
					break;
				case GestureSlideExt.GESTURE_RIGHT:
					goToPrePage();
					break;
				case GestureSlideExt.GESTURE_DOWN:
					//
					break;
				case GestureSlideExt.GESTURE_LEFT:
					goToNextPage();
					break;
				}
			}
		}).Buile();*/
    }
    
    public void openBook(String strFilePath) throws IOException {  
    	Log.d(TAG, "openBook---path = "+strFilePath);
    	if(strFilePath == null){
    		Toast.makeText(this, R.string.path_select_error, Toast.LENGTH_SHORT).toString();
    		ReaderBook.this.finish();
    		return;
    	}

    	
        book_file = new File(strFilePath);  
        if(!book_file.exists()){
        	Toast.makeText(ReaderBook.this, R.string.no_book_floder, Toast.LENGTH_SHORT).show();
        	ReaderBook.this.finish();
        	return;
        }
        
        long lLen = book_file.length();  
        m_mbBufLen = (int) lLen;  //最大不能超过2GB
        m_mbBuf = new RandomAccessFile(book_file, "r").getChannel().map(  
                FileChannel.MapMode.READ_ONLY, 0, lLen);  //把文件映射到内存
    } 
    
  //读取前一行文字
    protected byte[] readParagraphBack(int nFromPos) {  
        int nEnd = nFromPos;  
        int i;  
        byte b0, b1;  
        if (m_strCharsetName.equals("UTF-16LE")) {  
            i = nEnd - 2;  
            while (i > 0) {  
                b0 = m_mbBuf.get(i);  
                b1 = m_mbBuf.get(i + 1);  
                if (b0 == 0x0a && b1 == 0x00 && i != nEnd - 2) {  
                    i += 2;  //+2是为了补齐读取的长度，其中包括换行符号                
                    break;  
                }  
                i--;  
            }  
  
        } else if (m_strCharsetName.equals("UTF-16BE")) {  
            i = nEnd - 2;  
            while (i > 0) {  
                b0 = m_mbBuf.get(i);  
                b1 = m_mbBuf.get(i + 1);  
                if (b0 == 0x00 && b1 == 0x0a && i != nEnd - 2) {  
                    i += 2;  
                    break;  
                }  
                i--;  
            }  
        } else {  
            i = nEnd - 1;  
            while (i > 0) {  
                b0 = m_mbBuf.get(i);  
                if (b0 == 0x0a && i != nEnd - 1) {  
                    i++;  
                    break;  
                }  
                i--;  
            }  
        }  
        if (i < 0)  
            i = 0;  
        int nParaSize = nEnd - i;  
        int j;  
        byte[] buf = new byte[nParaSize];  
        for (j = 0; j < nParaSize; j++) {  
            buf[j] = m_mbBuf.get(i + j);  
        }  
        return buf;  
    }  
  
  
    //读取下一行文字
    protected byte[] readParagraphForward(int nFromPos) {  
        int nStart = nFromPos;  
        int i = nStart;  
        byte b0, b1;  
        if (m_strCharsetName.equals("UTF-16LE")) {  
            while (i < m_mbBufLen - 1) {  
                b0 = m_mbBuf.get(i++);  
                b1 = m_mbBuf.get(i++);  
                if (b0 == 0x0a && b1 == 0x00) {  
                    break;  
                }  
            }  
        } else if (m_strCharsetName.equals("UTF-16BE")) {  
            while (i < m_mbBufLen - 1) {  
                b0 = m_mbBuf.get(i++);  
                b1 = m_mbBuf.get(i++);  
                if (b0 == 0x00 && b1 == 0x0a) {  
                    break;  
                }  
            }  
        } else {  
            while (i < m_mbBufLen) {  
                b0 = m_mbBuf.get(i++);  
                if (b0 == 0x0a) {  
                    break;  
                }  
            }  
        }  
        int nParaSize = i - nStart;  
        byte[] buf = new byte[nParaSize];  
        for (i = 0; i < nParaSize; i++) {  
            buf[i] = m_mbBuf.get(nFromPos + i);  
        }  
        return buf;  
    }  
  
    protected Vector<String> pageDown() {  
        String strParagraph = "";  
        Vector<String> lines = new Vector<String>();  
        m_mbBufBegin = m_mbBufEnd;
        Log.d(TAG, "pageDown----lines.size = " + lines.size() + ", mLineCount = " + mLineCount + ", m_mbBufBegin = " + m_mbBufBegin);
        while (lines.size() < mLineCount && m_mbBufEnd < m_mbBufLen) {  
            byte[] paraBuf = readParagraphForward(m_mbBufEnd); 
            m_mbBufEnd += paraBuf.length;  
            try {  
                strParagraph = new String(paraBuf, m_strCharsetName);  
            } catch (UnsupportedEncodingException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
            String strReturn = "";  
            if (strParagraph.indexOf("\r\n") != -1) {  
                strReturn = "\r\n";  
                strParagraph = strParagraph.replaceAll("\r\n", "");  
            } else if (strParagraph.indexOf("\n") != -1) {  
                strReturn = "\n";  
                strParagraph = strParagraph.replaceAll("\n", "");  
            }  
  
            if(strParagraph.indexOf("  ") != 0){//这样做的目的是为了只有当这一行前两个字符为空格的时候,本行才会换行	        	
            	if(lines.size()>0){
	        		String str = lines.get(lines.size()-1);
	        		lines.remove(lines.size()-1);
	    			strParagraph = str + strParagraph;
	        	}
        	}
            
            if (strParagraph.length() == 0) {  
                lines.add(strParagraph);  
            }  
            while (strParagraph.length() > 0) {  
                int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,  
                        null);  
                lines.add(strParagraph.substring(0, nSize));  
                strParagraph = strParagraph.substring(nSize);  
                if (lines.size() >= mLineCount) {  
                    break;  
                }  
            }  
            if (strParagraph.length() != 0) {  
                try {  
                    m_mbBufEnd -= (strParagraph + strReturn)  
                            .getBytes(m_strCharsetName).length;  
                } catch (UnsupportedEncodingException e) {  
                    // TODO Auto-generated catch block  
                    e.printStackTrace();  
                }  
            }  
        }  
        return lines;  
    }  
  
    protected void pageUp() {  
        if (m_mbBufBegin < 0)  
            m_mbBufBegin = 0;  
        Vector<String> lines = new Vector<String>();  
        String strParagraph = "";  
        while (lines.size() < mLineCount && m_mbBufBegin > 0) {  
            Vector<String> paraLines = new Vector<String>();  
            byte[] paraBuf = readParagraphBack(m_mbBufBegin);  
            
            m_mbBufBegin -= paraBuf.length;  
            try {  
                strParagraph = new String(paraBuf, m_strCharsetName);  
            } catch (UnsupportedEncodingException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }           
            
            if(lines.size()>0){
        		String str = lines.get(lines.size()-1);
        		if(strParagraph.endsWith("\r\n")||strParagraph.endsWith("\n")){
	        		if(str.indexOf("  ") != 0){
	        			strParagraph = strParagraph+str;
	        			lines.remove(lines.size()-1);
	        		}        	
        		}
        	}
            
            strParagraph = strParagraph.replaceAll("\r\n", "");  
            strParagraph = strParagraph.replaceAll("\n", "");  
                     
            if (strParagraph.length() == 0) {  
                paraLines.add(strParagraph);  
            }  
            while (strParagraph.length() > 0) {  
                int nSize = mPaint.breakText(strParagraph, false, mVisibleWidth,  
                        null);  
                lines.add(strParagraph.substring(strParagraph.length()- nSize));  
                strParagraph = strParagraph.substring(0,strParagraph.length()- nSize);  
            }  
        }  
        while (lines.size() > mLineCount) {  
            try {  
                m_mbBufBegin += lines.get(0).getBytes(m_strCharsetName).length;  
                lines.remove(0);  
            } catch (UnsupportedEncodingException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
            }  
        }  
        m_mbBufEnd = m_mbBufBegin;  
        return;  
    }  
  
    protected void prePage() throws IOException {  
        if (m_mbBufBegin <= 0) {  
            m_mbBufBegin = 0;  
            m_isfirstPage=true;  
            return;  
        }else m_isfirstPage=false;  
        m_lines.clear();  
        pageUp(); //先计算前一页所需要读取的文字长短,并将，然后通过m_mbBufEnd赋值为这页的起始位置。读取上一页是通过m_mbBufBegin，读取下一页是通过m_mbBufEnd
        m_lines = pageDown();  
    }  
  
    public void nextPage() throws IOException {  
        if (m_mbBufEnd >= m_mbBufLen) {  
            m_islastPage=true;  
            return;  
        }else m_islastPage=false;  
        m_lines.clear();  
        m_mbBufBegin = m_mbBufEnd;  
        m_lines = pageDown();  
    }  
  
    private void updateContent(){
    	if (m_lines.size() == 0)  
            m_lines = pageDown();  

        onDraw(mCurPageCanvas);
    }
    public void onDraw(Canvas c) { 
        if (m_lines.size() == 0)  
            m_lines = pageDown();  
        if (m_lines.size() > 0) { 
            if (m_book_bg == null)  
                c.drawColor(m_backColor);  
            else  
                c.drawBitmap(m_book_bg, 0, 0, null);  
            int y = MARGINHEIGHT;  
            for (String strLine : m_lines) {  
                y += m_fontSize;  
                c.drawText(strLine, MARGINWIDTH, y, mPaint);  
            }  
        }  
        float fPercent = (float) (m_mbBufEnd * 1.0 / m_mbBufLen); //阅读的百分比
        DecimalFormat df = new DecimalFormat("#0.0");  
        String strPercent = df.format(fPercent * 100) + "%";  
        int nPercentWidth = (int) mPaint.measureText("999.9%") + 1;  
        c.drawText(strPercent, mWidth - nPercentWidth, mHeight - 5, mPaint);  
        //bookTextView.postInvalidate();
        mPageWidget.postInvalidate();
    }  
  
    public void setBgBitmap(Bitmap BG) {  
        m_book_bg = BG;  
    }  
     
    public boolean isfirstPage() {  
        return m_isfirstPage;  
    }  
    public boolean islastPage() {  
        return m_islastPage;  
    }  

    
    public String getSDPath(){ 
        File sdDir = null; 
        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);   //判断sd卡是否存在 
        if(sdCardExist)   
        {                               
          sdDir = Environment.getExternalStorageDirectory();//获取跟目录 
        }   
        return sdDir.toString();         
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //menu.add(0, 0, 0, "back");
        //menu.add(0, 1, 0, "forward");        
        return true;
    }

    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
    	
        switch (item.getItemId()) {
            case 0:
				try {
					prePage();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				updateContent();
                break;
            case 1:
            	try {
					nextPage();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				updateContent();
            	break;
        }
        return super.onOptionsItemSelected(item);
    }

	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		application.updateBookMark(application.getFilePath(), m_mbBufBegin);
		super.onPause();
	}

	@Override
	public boolean dispatchKeyEvent(KeyEvent event) {
		// TODO Auto-generated method stub
		if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN) {
			if(event.getAction() == KeyEvent.ACTION_UP){
				try {
					nextPage();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				updateContent();
			}
			return true;
		}else if (event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP) {
			if(event.getAction() == KeyEvent.ACTION_UP){
				try {
					prePage();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				updateContent();
			}
			return true;
		}
		
		return super.dispatchKeyEvent(event);
	}
	
/*	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return mGestureDetector.onTouchEvent(event);
	}*/

	void goToPrePage(){
		try {
			prePage();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		updateContent();
	}
	
	void goToNextPage(){
		try {
			nextPage();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		updateContent();
	}

	public boolean onTouch(View v, MotionEvent event) {
		boolean ret=false; 
		if (v == mPageWidget) {
			if (event.getAction() == MotionEvent.ACTION_DOWN) {
				mPageWidget.abortAnimation();
				mPageWidget.calcCornerXY(event.getX(), event.getY());
				
				onDraw(mCurPageCanvas);
				if (mPageWidget.DragToRight()) {
					try {
						prePage();
					} catch (IOException e) {
						e.printStackTrace();
					}
					if (isfirstPage()) {
						return false;
					}
					
				}else {
					try {
						nextPage();
					} catch (IOException e) {
						e.printStackTrace();
					}
					if (islastPage()) {
						return false;
					}
				}
				onDraw(mNextPageCanvas);
				mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
			}
			
			ret = mPageWidget.doTouchEvent(event);
		}
		
		return ret;
	}
	
	void resetDragOver(){
		if (mPageWidget.DragToRight()) {
			try {
				nextPage();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (isfirstPage()) {
				return ;
			}
			
		}else {
			try {
				prePage();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (islastPage()) {
				return ;
			}
		}
		
		mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
	}
}